package www.ph.adali.happy.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.Interpolator;
import android.view.animation.OvershootInterpolator;

import www.ph.adali.happy.Interface.IViewPageCallBack;
import www.ph.adali.happy.Utils.ScreenUtil;

import java.util.ArrayList;
import java.util.List;
/**
 * 启动页圆形指示器View
 */
public class CircleNavigatorView extends View implements IViewPageCallBack {

//    圆圈的半径
    private int mCircleRadius;
//    圆圈外边缘颜色
    private String mCircleOuterColor = "#3F3D56";
//    圆圈填充颜色
    private String mCircleFillColor = "#FFE663";
//    圆圈线宽
    private int mCircleStrokeWidth = 1;
//    圆圈之间的间隔
    private int mCircleSpacing = 15;
//    当前的圆圈的序号
    private int mCurrentNavigatorIndex;
//    总圆圈个数
    private int mTotalCircleNavigatorCount;
//    加速器
    private Interpolator mStartInterpolator = new OvershootInterpolator();
//    圆圈外圈画笔
    private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
//    圆圈外圈画笔
    private Paint mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private List<PointF> mCirclePoints = new ArrayList<PointF>();
    private float mIndicatorX;

    private boolean mTouchable;
    private OnCircleClickListener mCircleClickListener;
//    触摸X位置
    private float mDownX;
//    触摸Y位置
    private float mDownY;
    private int mTouchSlop;
//    是否跟随手指滑动
    private boolean mFollowTouchWithFinger = true;

    public CircleNavigatorView(Context context) {
        super(context);
        init(context);
    }

    private void init(Context context) {
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
        mCircleRadius = ScreenUtil.dip2px(context, 5);
        mCircleSpacing = ScreenUtil.dip2px(context, 18);
        mCircleStrokeWidth = ScreenUtil.dip2px(context, 1);
        mPaint.setColor(Color.parseColor(mCircleOuterColor));
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(mCircleStrokeWidth);
        mFillPaint.setColor(Color.parseColor(mCircleFillColor));
        mFillPaint.setStyle(Paint.Style.FILL);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
    }

    private int measureWidth(int widthMeasureSpec) {
        int mode = MeasureSpec.getMode(widthMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int result = 0;
        switch (mode) {
            case MeasureSpec.EXACTLY:
                result = width;
                break;
            case MeasureSpec.AT_MOST:
            case MeasureSpec.UNSPECIFIED:
                result = mTotalCircleNavigatorCount * mCircleRadius * 2 + (mTotalCircleNavigatorCount - 1) * mCircleSpacing + getPaddingLeft() + getPaddingRight() + mCircleStrokeWidth * 2;
                break;
            default:
                break;
        }
        return result;
    }

    private int measureHeight(int heightMeasureSpec) {
        int mode = MeasureSpec.getMode(heightMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        int result = 0;
        switch (mode) {
            case MeasureSpec.EXACTLY:
                result = height;
                break;
            case MeasureSpec.AT_MOST:
            case MeasureSpec.UNSPECIFIED:
                result = mCircleRadius * 2 + mCircleStrokeWidth * 2 + getPaddingTop() + getPaddingBottom();
                break;
            default:
                break;
        }
        return result;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        drawCircles(canvas);
        drawIndicator(canvas);
    }

    private void drawCircles(Canvas canvas) {
        for (int index = 0, totalCircle = mCirclePoints.size(); index < totalCircle; index++) {
            PointF pointF = mCirclePoints.get(index);
            canvas.drawCircle(pointF.x, pointF.y, mCircleRadius, mPaint);
        }
    }

    private void drawIndicator(Canvas canvas) {
        if (mCirclePoints.size() > 0) {
            canvas.drawCircle(mIndicatorX, (int) (getHeight() / 2.0f + 0.5f), mCircleRadius, mFillPaint);
        }
    }

    private void prepareCirclePoints() {
        mCirclePoints.clear();
        if (mTotalCircleNavigatorCount > 0) {
            int y = (int) (getHeight() / 2.0f + 0.5f);
            int centerSpacing = mCircleRadius * 2 + mCircleSpacing;
            int startX = mCircleRadius + (int) (mCircleStrokeWidth / 2.0f + 0.5f) + getPaddingLeft();
            for (int i = 0; i < mTotalCircleNavigatorCount; i++) {
                PointF pointF = new PointF(startX, y);
                mCirclePoints.add(pointF);
                startX += centerSpacing;
            }
            mIndicatorX = mCirclePoints.get(mCurrentNavigatorIndex).x;
        }
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        if (mFollowTouchWithFinger) {
            if (mCirclePoints.isEmpty()) {
                return;
            }
            int currentPosition = Math.min(mCirclePoints.size() - 1, position);
            int nextPosition = Math.min(mCirclePoints.size() - 1, position + 1);
            PointF current = mCirclePoints.get(currentPosition);
            PointF next = mCirclePoints.get(nextPosition);
            mIndicatorX = current.x + (next.x - current.x) * mStartInterpolator.getInterpolation(positionOffset);
            invalidate();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (mTouchable) {
                    mDownX = x;
                    mDownY = y;
                    return true;
                }
                break;
            case MotionEvent.ACTION_UP:
                if (mCircleClickListener != null) {
                    if (Math.abs(x - mDownX) <= mTouchSlop && Math.abs(y - mDownY) <= mTouchSlop) {
                        float max = Float.MAX_VALUE;
                        int index = 0;
                        for (int i = 0; i < mCirclePoints.size(); i++) {
                            PointF pointF = mCirclePoints.get(i);
                            float offset = Math.abs(pointF.x - x);
                            if (offset < max) {
                                max = offset;
                                index = i;
                            }
                        }
                        mCircleClickListener.onClick(index);
                    }
                }
                break;
            default:
                break;
        }
        return super.onTouchEvent(event);
    }

    @Override
    public void onPageSelected(int position) {
        mCurrentNavigatorIndex = position;
        if (!mFollowTouchWithFinger) {
            mIndicatorX = mCirclePoints.get(mCurrentNavigatorIndex).x;
            invalidate();
        }
    }

    @Override
    public void onPageScrollStateChanged(int state) {
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        prepareCirclePoints();
    }

    @Override
    public void notifyDataSetChanged() {
        prepareCirclePoints();
        invalidate();
    }

    public void setCircleCount(int count) {
        mTotalCircleNavigatorCount = count;
    }

    public void setCircleClickListener(OnCircleClickListener circleClickListener) {
        if (!mTouchable) {
            mTouchable = true;
        }
        mCircleClickListener = circleClickListener;
    }

    public interface OnCircleClickListener {
        void onClick(int index);
    }
}